package com.gzc.just.play.last.war.common.serializer;

import com.google.protobuf.MessageLite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Method;
import java.util.zip.GZIPInputStream;

/**
 * Protobuf消息反序列化器抽象基类
 * 
 * 使用模板方法模式，提供通用的反序列化流程：
 * 1. 解密（可选）
 * 2. 解压缩（可选）  
 * 3. Protobuf解析
 * 
 * 子类只需指定消息类型，无需重复实现反序列化逻辑。
 * 如果需要添加新的预处理步骤（如签名验证），只需修改此基类。
 * 
 * @param <T> Protobuf消息类型
 */
public abstract class AbstractProtobufDeserializer<T extends MessageLite> implements MessageDeserializer<T> {
    
    private static final Logger logger = LoggerFactory.getLogger(AbstractProtobufDeserializer.class);
    
    private final Class<T> messageClass;
    private final Method parseFromMethod;
    private final boolean compressionEnabled;
    private final boolean encryptionEnabled;
    
    /**
     * 构造函数
     * @param messageClass Protobuf消息类型
     */
    protected AbstractProtobufDeserializer(Class<T> messageClass) {
        this(messageClass, false, false);
    }
    
    /**
     * 构造函数
     * @param messageClass Protobuf消息类型
     * @param compressionEnabled 是否启用解压缩
     * @param encryptionEnabled 是否启用解密
     */
    protected AbstractProtobufDeserializer(Class<T> messageClass, boolean compressionEnabled, boolean encryptionEnabled) {
        this.messageClass = messageClass;
        this.compressionEnabled = compressionEnabled;
        this.encryptionEnabled = encryptionEnabled;
        this.parseFromMethod = resolveParseFromMethod(messageClass);
    }
    
    /**
     * 通过反射获取Protobuf的parseFrom静态方法
     */
    private Method resolveParseFromMethod(Class<T> clazz) {
        try {
            return clazz.getMethod("parseFrom", byte[].class);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Class " + clazz.getName() + " does not have parseFrom(byte[]) method", e);
        }
    }
    
    /**
     * 模板方法：反序列化流程
     * 子类无需覆盖此方法，除非需要完全自定义流程
     */
    @Override
    public T deserialize(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            logger.warn("Cannot deserialize null or empty bytes for {}", messageClass.getSimpleName());
            return null;
        }
        
        try {
            byte[] processedBytes = bytes;
            
            // Step 1: 解密（如果启用）
            if (encryptionEnabled) {
                processedBytes = decrypt(processedBytes);
            }
            
            // Step 2: 解压缩（如果启用）
            if (compressionEnabled) {
                processedBytes = decompress(processedBytes);
            }
            
            // Step 3: Protobuf解析
            return parseProtobuf(processedBytes);
            
        } catch (Exception e) {
            logger.error("Failed to deserialize {} message: {}", messageClass.getSimpleName(), e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 解密数据
     * 子类可覆盖此方法实现自定义解密逻辑
     */
    protected byte[] decrypt(byte[] encryptedBytes) throws Exception {
        // 默认实现：简单XOR解密（示例，实际应使用更安全的算法）
        // 子类可覆盖实现AES等加密算法
        return encryptedBytes; // 默认不做处理
    }
    
    /**
     * 解压缩数据
     * 子类可覆盖此方法实现自定义解压缩逻辑
     */
    protected byte[] decompress(byte[] compressedBytes) throws Exception {
        // 默认实现：GZIP解压缩
        try (ByteArrayInputStream bis = new ByteArrayInputStream(compressedBytes);
             GZIPInputStream gis = new GZIPInputStream(bis);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            
            byte[] buffer = new byte[1024];
            int len;
            while ((len = gis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        }
    }
    
    /**
     * 解析Protobuf消息
     */
    @SuppressWarnings("unchecked")
    protected T parseProtobuf(byte[] bytes) throws Exception {
        return (T) parseFromMethod.invoke(null, bytes);
    }
    
    /**
     * 获取消息类型
     */
    public Class<T> getMessageClass() {
        return messageClass;
    }
    
    /**
     * 是否启用压缩
     */
    public boolean isCompressionEnabled() {
        return compressionEnabled;
    }
    
    /**
     * 是否启用加密
     */
    public boolean isEncryptionEnabled() {
        return encryptionEnabled;
    }
}
